/*
 * Dcm_UDS0x14.c
 *
 *  Created on: 2018-1-16
 *      Author: Shute
 */
#include "UDS.h"


/****************************************************************
	     UDS:ClearDiagnosticInformation (14 hex) service
 ***************************************************************/
#if(STD_ON == DCM_UDS_SERVICE0X14_ENABLED)
/********************************/
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
FUNC(Std_ReturnType, DCM_CODE)Dcm_UDS0x14(
		Dcm_OpStatusType OpStatus,
		uint8  ProtocolCtrlId,
		P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_VAR) ErrorCode)
{
	uint8   MsgCtrlId;
	uint8   TxChannelCtrlIndex;
	uint8   TxChannelCfgIndex;
	uint16  Offset;
	uint32  groupOfDTC;
	Dem_ReturnClearDTCType returnClearDTC;
	Std_ReturnType ret;
	static boolean Clear_process = FALSE;

	/*************************************************/
	/*if the required protocol is configuted,get the index of runtime datum*/
	MsgCtrlId =  Dcm_ProtocolCtrl[ProtocolCtrlId].MsgCtrlIndex;

	/*check the massage length*/
	if (DCM_UDS0X14_REQ_DATA_LENGTH != Dcm_MsgCtrl[MsgCtrlId].MsgContext.ReqDataLen)
	{
		/*the length of massage is not correct,send NRC 0x13*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}

	/*************************************************/
#if(STD_ON == DCM_SESSION_FUNC_ENABLED)
	/*session check,check whether the current session supports the request service*/
	ret = DsdInternal_SesCheck(ProtocolCtrlId,SID_CLEAR_DIAGNOSTIC_INFORMATION);
	if(E_NOT_OK == ret)
	{
		/****@req DCM-FUNR-073[DCM211]****/
		/*the current session does not support the request service,send NRC = 0x7F*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_SERVICENOTSUPPORTEDINACTIVESESSION);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}
	else
	{
		ret = DsdInternal_SubSesCheck(ProtocolCtrlId,SID_CLEAR_DIAGNOSTIC_INFORMATION);
		if(E_NOT_OK == ret)
		{
			/****SWS_Dcm_00616****/
			/*the current session does not support the request sub service,send NRC = 0x7E*/
			(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_SUBFUNCTIONNOTSUPPORTEDINACTIVESESSION);
			DsdInternal_ProcessingDone(ProtocolCtrlId);
			return E_NOT_OK;
		}
	}
#endif

	/*************************************************/
#if(STD_ON == DCM_SECURITY_FUNC_ENABLED)
	/*security check,check whether the current security supports the request service*/
	ret = DsdInternal_SecurityCheck(ProtocolCtrlId,SID_CLEAR_DIAGNOSTIC_INFORMATION);
	if(E_NOT_OK == ret)
	{
		/****@req DCM-FUNR-074[DCM217]****/
		/*the current security does not support the request service,send NRC = 0x33*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_SECURITYACCESSDENIED);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}
#endif

	/*************************************************/
	/*get and assemble DTC, high byte first*/
	groupOfDTC = (((uint32)(Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[1]))<< 16u)\
	           	      |(((uint32)(Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[2]))<<8u)\
	                    |((uint32)(Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[3]));

	returnClearDTC = Dem_DcmCheckClearParameter(	groupOfDTC,
													DEM_DTC_FORMAT_UDS,
													DEM_DTC_ORIGIN_PRIMARY_MEMORY);

	switch(returnClearDTC)
	{
		case DEM_CLEAR_PENDING:
			ret = DCM_E_PENDING;
			Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
			break;
		case DEM_CLEAR_WRONG_DTC:
			/*Server does not support the required groupOfDTC,send NRC 0x31*/
			(void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_REQUESTOUTOFRANGE);
			DsdInternal_ProcessingDone(ProtocolCtrlId);
			ret = E_NOT_OK;
			break;
		case DEM_CLEAR_FAILED:
			/*internal conditions within the server prevent the
			   clearing of DTC related information stored in the server,sent NRC 0x22*/
			(void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_CONDITIONSNOTCORRECT);
			DsdInternal_ProcessingDone(ProtocolCtrlId);
			ret = E_NOT_OK;
			break;
		case DEM_CLEAR_OK:
			if (Dcm_DspCfg.pDcmDspClearDTC != NULL_PTR)
			{
				if (Dcm_DspCfg.pDcmDspClearDTC->DcmDsp_ClearDTCCheckFnc != NULL_PTR)
				{
					ret = Dcm_DspCfg.pDcmDspClearDTC->DcmDsp_ClearDTCCheckFnc(groupOfDTC, ErrorCode);
					if (ret != E_OK)
					{
						(void)DsdInternal_SetNrc(ProtocolCtrlId, *ErrorCode);
						DsdInternal_ProcessingDone(ProtocolCtrlId);
					}
				}
			}
			if ((OpStatus == DCM_PENDING) && (Clear_process == TRUE))
			{
                Clear_process = FALSE;
                /*clear is successful,assemble and send the positive response*/
                TxChannelCtrlIndex = Dcm_MsgCtrl[MsgCtrlId].Dcm_TxCtrlChannelIndex;
                TxChannelCfgIndex = Dcm_ChannelCtrl[TxChannelCtrlIndex].Dcm_ChannelCfgIndex;
                Offset = (Dcm_DslCfg.pDcmChannelCfg)[TxChannelCfgIndex].offset;
                /* check tx data length */
                if((0x01u) > (Dcm_DslCfg.pDcmChannelCfg[TxChannelCfgIndex].Dcm_DslBufferSize))
                {
                    /*Pdu length is bigger than buffer size,ignore the request message */
                    (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_RESPONSETOOLONG);
                    DsdInternal_ProcessingDone(ProtocolCtrlId);
                    return E_NOT_OK;
                }
                SchM_Enter_Dcm(Dcm_Channel);
                Dcm_Channel[Offset] = 0x54;   /*response SID*/
                SchM_Exit_Dcm(Dcm_Channel);
                SchM_Enter_Dcm(Dcm_MsgCtrl);
                Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResMaxDataLen = 0x01;
                Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResDataLen    = 0x01;
                Dcm_MsgCtrl[MsgCtrlId].MsgContext.pResData      = &Dcm_Channel[Offset];
                SchM_Exit_Dcm(Dcm_MsgCtrl);
                DsdInternal_ProcessingDone(ProtocolCtrlId);
			}
			break;
		default:
		    break;
	}

	if (E_OK == ret)
	{
		/*invoke the corresponding API provided by DEM*/
		returnClearDTC = Dem_DcmClearDTC(	groupOfDTC,
										DEM_DTC_FORMAT_UDS,
										DEM_DTC_ORIGIN_PRIMARY_MEMORY);
		Clear_process = TRUE;
		switch (returnClearDTC)
		{
			case DEM_CLEAR_OK:
				/*clear is successful,assemble and send the positive response*/
				TxChannelCtrlIndex = Dcm_MsgCtrl[MsgCtrlId].Dcm_TxCtrlChannelIndex;
				TxChannelCfgIndex = Dcm_ChannelCtrl[TxChannelCtrlIndex].Dcm_ChannelCfgIndex;
				Offset = (Dcm_DslCfg.pDcmChannelCfg)[TxChannelCfgIndex].offset;
			    /* check tx data length */
			    if((0x01u) > (Dcm_DslCfg.pDcmChannelCfg[TxChannelCfgIndex].Dcm_DslBufferSize))
			    {
			        /*Pdu length is bigger than buffer size,ignore the request message */
			        (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_RESPONSETOOLONG);
			        DsdInternal_ProcessingDone(ProtocolCtrlId);
			        return E_NOT_OK;
			    }
				SchM_Enter_Dcm(Dcm_Channel);
				Dcm_Channel[Offset] = 0x54;   /*response SID*/
				SchM_Exit_Dcm(Dcm_Channel);
				SchM_Enter_Dcm(Dcm_MsgCtrl);
				Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResMaxDataLen = 0x01;
				Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResDataLen    = 0x01;
				Dcm_MsgCtrl[MsgCtrlId].MsgContext.pResData      = &Dcm_Channel[Offset];
				SchM_Exit_Dcm(Dcm_MsgCtrl);
				DsdInternal_ProcessingDone(ProtocolCtrlId);
				break;
			case DEM_CLEAR_WRONG_DTC:
				/*Server does not support the required groupOfDTC,send NRC 0x31*/
				(void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_REQUESTOUTOFRANGE);
				DsdInternal_ProcessingDone(ProtocolCtrlId);
				ret = E_NOT_OK;
				break;
			case DEM_CLEAR_BUSY:
			case DEM_CLEAR_FAILED:
				/*internal conditions within the server prevent the
				   clearing of DTC related information stored in the server,sent NRC 0x22*/
				(void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_CONDITIONSNOTCORRECT);
				DsdInternal_ProcessingDone(ProtocolCtrlId);
				ret = E_NOT_OK;
				break;
			case DEM_CLEAR_PENDING:
				ret = DCM_E_PENDING;
	            Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
				break;
			case DEM_CLEAR_MEMORY_ERROR:
				(void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_GENERALPROGRAMMINGFAILURE);
				DsdInternal_ProcessingDone(ProtocolCtrlId);
				ret = E_NOT_OK;
				break;
			default:
				/*the unexpected return value is present,send NRC 0x22*/
				(void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_CONDITIONSNOTCORRECT);
				DsdInternal_ProcessingDone(ProtocolCtrlId);
				ret = E_NOT_OK;
				break;
		}
	}
	return (ret);
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"
#endif
